package org.fuys.coder.domain.act.lottery.service.draw.impl;

import lombok.extern.slf4j.Slf4j;
import org.fuys.coder.common.entity.Pair;
import org.fuys.coder.domain.act.lottery.model.req.draw.DrawReq;
import org.fuys.coder.domain.act.lottery.model.res.draw.DrawResult;
import org.fuys.coder.domain.act.lottery.service.algorithm.impl.AliasAlgorithm;
import org.fuys.coder.domain.act.lottery.service.algorithm.impl.AlienBillAlgorithm;
import org.fuys.coder.domain.act.lottery.service.draw.AbstractDrawService;
import org.fuys.coder.domain.act.lottery.service.strategy.factory.LotteryStrategyFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;

/**
 * @projectName: fuys-low-coder
 * @package: org.fuys.coder.domain.lottery.service.draw.impl
 * @className: DefaultDrawServiceImpl
 * @author: WangJing
 * @description: 默认抽奖结果生成实现类 其他的 如对排除奖品的不同处理 留给其他实现类 这里的默认处理是直接返回未中奖
 * @date: 2024/7/7 23:04
 * @version: 1.0
 */
@Service
@Slf4j
public class DefaultDrawServiceImpl extends AbstractDrawService {

    @Resource
    private AlienBillAlgorithm alienBillAlgorithm;

    @Resource
    private AliasAlgorithm aliasAlgorithm;

    @Override
    protected Integer doDraw(DrawReq req) {
        //获取抽奖策略类型
        final Pair<Integer, Integer> strategyType = req.getStrategyType();
        //优先采用预先计算的高效抽奖算法
        final Integer result = aliasAlgorithm.randomDraw(strategyType);
        if(result==null) {
            //说明某些原因没能成功 则获取各个概率信息 进行朴素抽奖
            final List<Pair<Integer, Double>> odds = LotteryStrategyFactory.getStrategyOddInfo(strategyType.getLeft()
                    , strategyType.getRight());
            if (check(odds)) {
                //连各个奖品的权重没有找到 为了避免大量错误堆积 直接返回未中奖
                log.error("抽奖概率未发现:" + req);
                return null;
            }
            return alienBillAlgorithm.randomDraw(strategyType);
        }
        return result;
    }

    @Override
    protected boolean check(List<Pair<Integer, Double>> odds) {
        return super.check(odds);
    }

    @Override
    protected DrawResult buildResult(Integer integer,DrawReq req) {
        if(ObjectUtils.isEmpty(integer)){
            return new DrawResult(null,"未中奖",false);
        }
        if(!ObjectUtils.isEmpty(req.getExcludeList())){
            if(req.getExcludeList().contains(integer)){
                return new DrawResult(null,"未中奖",true);
            }
        }
        if(integer<=0){
            return new DrawResult(null,"未中奖",true);
        }
        return new DrawResult(integer,"中奖",true);
    }
}
